package com.xiebishe.mylibrary.net.retrofit.fastjsonConverter;

import android.text.TextUtils;

import com.alibaba.fastjson.JSON;
import com.xiebishe.mylibrary.net.retrofit.unescaper.AggregateTranslator;
import com.xiebishe.mylibrary.net.retrofit.unescaper.CharSequenceTranslator;
import com.xiebishe.mylibrary.net.retrofit.unescaper.EntityArrays;
import com.xiebishe.mylibrary.net.retrofit.unescaper.LookupTranslator;
import com.xiebishe.mylibrary.net.retrofit.unescaper.NumericEntityUnescaper;


import java.io.IOException;
import java.lang.reflect.Type;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import okhttp3.ResponseBody;
import retrofit2.Converter;


public class FastJsonResponseBodyDecodeConverter<T> implements Converter<ResponseBody, T> {
    //配置：用于html标签转义字符的反转义
    private static CharSequenceTranslator UNESCAPE_HTML4_NET =
            new AggregateTranslator(
                    new LookupTranslator(EntityArrays.BASIC_UNESCAPE_NET()),
                    new LookupTranslator(EntityArrays.ISO8859_1_UNESCAPE()),
                    new LookupTranslator(EntityArrays.HTML40_EXTENDED_UNESCAPE()),
                    new NumericEntityUnescaper()
            );
    //    private static ParserConfig parserConfig;
    private Type type;

//    static {
//        parserConfig = new ParserConfig();
//        parserConfig.getDeserializers().put(String.class, StringCodecDelHtml.instance);
//    }

    public FastJsonResponseBodyDecodeConverter(Type type) {
        this.type = type;
    }

    @Override
    public T convert(ResponseBody value) throws IOException {
        String origin = value.string();
        String newResponseBody = unescapeAndDelHTMLTag_net(origin);   //反转义html标签，并删除.然后去除收尾多余换行
        return JSON.parseObject(newResponseBody, type);
    }
    /**
     * 反转义html标签，并且删除标签内容
     * eg.  "&lt;div&gt;猪蹄也可摘星辰&lt;/div&gt;"    ----->  "猪蹄也可摘星辰"
     * <p>
     * 【用于网络解析，这里指：没有经过Json解析的网络原始数据！！！】
     *
     * @param input
     * @return
     */
    public static String unescapeAndDelHTMLTag_net(String input) {
        if (TextUtils.isEmpty(input)) {
            return "";
        }
        return trimLine(delHTMLTag_net(unescapeHtmlTag_net(input)));
    }
    /**
     * 去除文本最前面和最后面的若干个"\n","\t"
     *
     * @param str
     * @return
     */
    public static String trimLine(String str) {
        if (TextUtils.isEmpty(str)) {
            return "";
        }
        return str.replaceAll("^\\s+", "").replaceAll("\\s+$", "");//去除开头和结尾的“\n”换行符
    }
    /**
     * html标签转义字符的反转义
     * eg.  "&lt;div&gt;猪蹄也可摘星辰&lt;/div&gt;"    ----->  "<div>猪蹄也可摘星辰</div>"
     *
     * @param input
     * @return
     */
    public static String unescapeHtmlTag_net(final String input) {
        if (TextUtils.isEmpty(input)) {
            return "";
        }
        return UNESCAPE_HTML4_NET.translate(input);
    }
    /**
     * 删除文本中的script、style和HTML标签
     * eg.  "<div>猪蹄也可摘星辰</div>"    ----->  "猪蹄也可摘星辰"
     * <p>
     * 【会考虑双引号前的反斜杠(json内)，用于网络请求】
     *
     * @param htmlStr
     * @return
     */
    private static String delHTMLTag_net(String htmlStr) {
        if (TextUtils.isEmpty(htmlStr)) {
            return "";
        }
        if (htmlStr.indexOf('<') >= 0) {
            String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
            String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式
            String regEx_html = "(&([a-zA-Z]{1,10}|(gt|lt|amp|nbsp));)"; //定义HTML标签的正则表达式 pre: <([^>"]*?("[^"]+?")?[^>"]*)*?>

            Pattern p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
            Matcher m_script = p_script.matcher(htmlStr);
            htmlStr = m_script.replaceAll(""); //过滤script标签

            Pattern p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
            Matcher m_style = p_style.matcher(htmlStr);
            htmlStr = m_style.replaceAll(""); //过滤style标签

            StringBuilder stringBuilder = new StringBuilder(htmlStr);
            int lastLt = -1;
            boolean doubleQuate = false;
            boolean inString = false;
            for (int i = 0; i < stringBuilder.length(); i++) {
                char c = stringBuilder.charAt(i);
                if (c == '"' && i == 0 || c == '"' && i > 0 && stringBuilder.charAt(i - 1) != '\\') {
                    inString = !inString;
                    if (inString) {
                        lastLt = -1;
                        doubleQuate = false;
                    }
                    continue;
                }
                if (inString) {
                    if (c == '<' && !doubleQuate)
                        lastLt = i;
                    else if (c == '"' && i > 0 && stringBuilder.charAt(i - 1) == '\\' && !doubleQuate) {
                        doubleQuate = true;
                    } else if (c == '"' && i > 1 && stringBuilder.charAt(i - 1) == '\\' && stringBuilder.charAt(i - 2) != '\\') {
                        doubleQuate = false;
                    } else if (c == '>' && lastLt >= 0 && !doubleQuate) {
                        stringBuilder.delete(lastLt, i + 1);
                        i = lastLt - 1;
                        lastLt = -1;
                    }
                }
            }
            htmlStr = stringBuilder.toString();
            Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
            Matcher m_html = p_html.matcher(htmlStr);
            htmlStr = m_html.replaceAll(""); //过滤html标签

            return htmlStr.trim(); //返回文本字符串
        } else {
            return htmlStr;
        }
    }

}


